package com.ls.service.impl;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ls.config.satoken.SaTokenUtilPy;
import com.ls.controller.linkman.model.*;
import com.ls.entity.*;
import com.ls.mapper.LinkmanMapper;
import com.ls.service.*;
import com.ls.utils.ResultData;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.pinyin4j.PinyinHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.ls.constant.SystemConstants.*;

/**
 * <p>
 * 联系人表，与customer关联 服务实现类
 * </p>
 *
 * @author pengyu
 * @since 2024-11-20
 */
@Service
@Slf4j
public class LinkmanServiceImpl extends ServiceImpl<LinkmanMapper, Linkman> implements ILinkmanService {
    private final ICompanyService companyService;
    private final IPhoneRecordService phoneRecordService;
    @Lazy
    private final ITeamService teamService;
    @Lazy
    private final ILabelService labelService;
    private final IBlackListService blackListService;
    private final AIService aiService;
    private final ISmsTemplateService smsTemplateService;
    @Lazy
    private final IRuleLinkmanService ruleLinkmanService;
    @Lazy
    private final ISmsRuleService smsRuleService;
    @Autowired
    public LinkmanServiceImpl(
            ICompanyService companyService,
            IPhoneRecordService phoneRecordService,
            @Lazy ITeamService teamService,
            @Lazy ILabelService labelService,
            IBlackListService blackListService,
            AIService aiService,
            ISmsTemplateService smsTemplateService,
            @Lazy IRuleLinkmanService ruleLinkmanService,
            @Lazy ISmsRuleService smsRuleService
    ) {
        this.companyService = companyService;
        this.phoneRecordService = phoneRecordService;

        this.teamService = teamService;
        this.labelService = labelService;
        this.blackListService = blackListService;
        this.aiService = aiService;
        this.smsTemplateService = smsTemplateService;
        this.ruleLinkmanService = ruleLinkmanService;
        this.smsRuleService = smsRuleService;
    }

    @Override
    public ResultData getLinkmanById(Long linkmanId) {
        Linkman linkman = getById(linkmanId);
        if (linkman == null) {
            return ResultData.failure("联系人不存在");
        }
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        List<String> reasonList= new ArrayList<>();
        Integer isInBlack = isInBlackList(linkman.getLinkmanPhone());
        if (isInBlack==NUMBER_0){
            linkman.setCanSelect(NUMBER_0);
            reasonList.add("当前客户在黑名单中");
            linkman.setReasonList(reasonList);
        } else {
            linkman.setCanSelect(NUMBER_1);
        }
        if (linkman.getLabelId() != null) {
            linkman.setLabelName(labelService.getById(linkman.getLabelId()).getLabelName());
        } else {
            linkman.setLabelName("未分配标签人员");
            linkman.setLabelId((long) -1);
        }
        if (linkman.getTeamId() != null) {
            linkman.setTeamName(teamService.getById(linkman.getTeamId()).getTeamName());
        } else {
            linkman.setTeamName("未分配分组人员");
            linkman.setTeamId((long) -1);
        }
        return ResultData.successData(linkman);
    }

    @Override
    public ResultData pageList(QueryLinkmanModel model) {
        log.info("联系人查询参数：{}", model);
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        log.info("当前用户ID：{}", customerId);
        LambdaQueryWrapper<Linkman> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Linkman::getCustomerId, customerId)
                .eq(Linkman::getValidFlag, VALID_TRUE);
        if (model.getType() == null || model.getType() != null && model.getType() != NUMBER_0) {
            if (model.getSearch() != null) {
                wrapper.and(q -> q
                        .like(Linkman::getLinkmanName, model.getSearch())
                        .or()
                        .like(Linkman::getFullSpellName, model.getSearch())
                        .or()
                        .like(Linkman::getShortSpellName, model.getSearch())
                        .or()
                        .like(Linkman::getLinkmanPhone, model.getSearch())
                );
            }
            wrapper.eq(model.getLinkmanType() != null, Linkman::getLinkmanType, model.getLinkmanType())
                    .orderByDesc(Linkman::getCreateTime);
            if (model.getType() == null) {
                wrapper.eq(model.getTeamId() != null, Linkman::getTeamId, model.getTeamId())
                        .eq(model.getLabelId() != null, Linkman::getLabelId, model.getLabelId());
            } else if (model.getType() == NUMBER_1) {
                wrapper.isNull(Linkman::getTeamId);
            } else if (model.getType() == NUMBER_2) {
                wrapper.isNull(Linkman::getLabelId);
            }
            // 在构建完所有条件后执行查询，使用关联查询获取部门名称和标签名称
            List<Linkman> linkmanList = baseMapper.selectList(wrapper);
            linkmanList.forEach(l -> {
                int count = blackListService.count(
                        new LambdaQueryWrapper<BlackList>()
                                .eq(BlackList::getCustomerId, customerId)
                                .eq(BlackList::getBlackPhone, l.getLinkmanPhone())
                );
                List<String> reasonList= new ArrayList<>();
                Integer isInBlack = isInBlackList(l.getLinkmanPhone());
                if (isInBlack==NUMBER_0) {
                    l.setCanSelect(NUMBER_0);
                    reasonList.add("当前客户在黑名单中");
                    l.setReasonList(reasonList);
                } else {
                    l.setCanSelect(NUMBER_1);
                }
                if (l.getLabelId() != null) {
                    l.setLabelName(labelService.getById(l.getLabelId()).getLabelName());
                } else {
                    l.setLabelName("未分配标签人员");
                    l.setLabelId((long) -1);
                }
                if (l.getTeamId() != null) {
                    l.setTeamName(teamService.getById(l.getTeamId()).getTeamName());
                } else {
                    l.setTeamName("未分配分组人员");
                    l.setTeamId((long) -1);
                }
            });
            log.info("联系人查询结果：{}", linkmanList);
            return ResultData.successData(linkmanList);
        } else {
            wrapper.select(Linkman::getLinkmanPhone);
            // 获取已存在的电话号码列表
            List<String> existPhones = list(wrapper).stream()
                    .map(Linkman::getLinkmanPhone)
                    .collect(Collectors.toList());
            log.info("已存在的电话号码：{}", existPhones);
            // 修正查询逻辑：明确指定查询字段并转换结果类型
            List<PhoneRecord> phoneRecords = phoneRecordService.list(
                    new LambdaQueryWrapper<PhoneRecord>()
                            .select(PhoneRecord::getOuterPhone, PhoneRecord::getStartTime)
                            .like(StringUtils.isNotBlank(model.getSearch()), PhoneRecord::getOuterPhone, model.getSearch())
                            .eq(PhoneRecord::getCustomerId, customerId)
//                            .groupBy(PhoneRecord::getOuterPhone)
                            .notIn(!existPhones.isEmpty(), PhoneRecord::getOuterPhone, existPhones)
                            .orderByDesc(PhoneRecord::getStartTime)
            );
            log.info("通话记录：{}", phoneRecords);
            //对通话记录去重
            List<PhoneRecord> distinctRecords = phoneRecords.stream()
                    .collect(Collectors.toMap(
                            PhoneRecord::getOuterPhone,
                            p -> p,
                            (existing, replacement) ->
                                    existing.getStartTime().isAfter(replacement.getStartTime()) ? existing : replacement
                    ))
                    .values().stream()
                    .collect(Collectors.toList());
            log.info("去重后的通话记录：{}", distinctRecords);
            // 将PhoneRecord转换为Linkman结构返回
            List<Linkman> linkmanList = distinctRecords.stream()
                    .map(p -> new Linkman()
                            .setLinkmanPhone(p.getOuterPhone())
                            .setCreateTime(p.getStartTime())
                            .setCustomerId(customerId)
                            .setValidFlag(VALID_TRUE))
                    .collect(Collectors.toList());

            return ResultData.successData(linkmanList);
        }
    }
    /**联系人数量*/
    @Override
    public ResultData getLinkmanCount(QueryLinkmanModel model) {
        log.info("联系人查询参数：{}", model);
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        log.info("当前用户ID：{}", customerId);
        LambdaQueryWrapper<Linkman> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Linkman::getCustomerId, customerId)
                .eq(Linkman::getValidFlag, VALID_TRUE);
        if (model.getType() == null || model.getType() != null && model.getType() != NUMBER_0) {
            if (model.getSearch() != null) {
                wrapper.and(q -> q
                        .like(Linkman::getLinkmanName, model.getSearch())
                        .or()
                        .like(Linkman::getFullSpellName, model.getSearch())
                        .or()
                        .like(Linkman::getShortSpellName, model.getSearch())
                        .or()
                        .like(Linkman::getLinkmanPhone, model.getSearch())
                );
            }
            wrapper.eq(model.getLinkmanType() != null, Linkman::getLinkmanType, model.getLinkmanType())
                    .orderByDesc(Linkman::getCreateTime);
            if (model.getType() == null) {
                wrapper.eq(model.getTeamId() != null, Linkman::getTeamId, model.getTeamId())
                        .eq(model.getLabelId() != null, Linkman::getLabelId, model.getLabelId());
            } else if (model.getType() == NUMBER_1) {
                wrapper.isNull(Linkman::getTeamId);
            } else if (model.getType() == NUMBER_2) {
                wrapper.isNull(Linkman::getLabelId);
            }
            // 在构建完所有条件后执行查询，使用关联查询获取部门名称和标签名称
            Integer linkmanLists = count(wrapper);
            log.info("联系人查询结果：{}", linkmanLists);
            return ResultData.successData(linkmanLists);
        } else {
            wrapper.select(Linkman::getLinkmanPhone);
            // 获取已存在的电话号码列表
            List<String> existPhones = list(wrapper).stream()
                    .map(Linkman::getLinkmanPhone)
                    .collect(Collectors.toList());
            log.info("已存在的电话号码：{}", existPhones);
            // 修正查询逻辑：明确指定查询字段并转换结果类型
            List<PhoneRecord> phoneRecords = phoneRecordService.list(
                    new LambdaQueryWrapper<PhoneRecord>()
                            .select(PhoneRecord::getOuterPhone, PhoneRecord::getStartTime)
                            .like(StringUtils.isNotBlank(model.getSearch()), PhoneRecord::getOuterPhone, model.getSearch())
                            .eq(PhoneRecord::getCustomerId, customerId)
//                            .groupBy(PhoneRecord::getOuterPhone)
                            .notIn(!existPhones.isEmpty(), PhoneRecord::getOuterPhone, existPhones)
                            .orderByDesc(PhoneRecord::getStartTime)
            );
            log.info("通话记录：{}", phoneRecords);
            //对通话记录去重
            List<PhoneRecord> distinctRecords = phoneRecords.stream()
                    .collect(Collectors.toMap(
                            PhoneRecord::getOuterPhone,
                            p -> p,
                            (existing, replacement) ->
                                    existing.getStartTime().isAfter(replacement.getStartTime()) ? existing : replacement
                    ))
                    .values().stream()
                    .collect(Collectors.toList());

            return ResultData.successData(distinctRecords.size());
        }
    }

    // 新增工具方法（类内私有方法）
    private String getFirstLetter(String chinese) {
        if (StringUtils.isBlank(chinese)) return "#";
        char firstChar = chinese.charAt(0);
        if (Character.toString(firstChar).matches("[\\u4E00-\\u9FA5]")) {
            return PinyinHelper.toHanyuPinyinStringArray(firstChar)[0].substring(0, 1).toUpperCase();
        } else if (Character.isLetter(firstChar)) {
            return Character.toString(firstChar).toUpperCase();
        }
        return "#";
    }

    @Override
    public ResultData add(AddLinkmanModel model) {
        log.info("新增联系人参数：{}", model);
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        if (!model.getLinkmanPhone().matches(PHONE_NUMBER_VALID_REGEX)) {
            return ResultData.failure("手机号码格式错误");
        }
        //根据用户id查询用户企业
        Long companyId = null;
        if (model.getCompanyId() == null) {
            Company company = companyService.getOne(new LambdaQueryWrapper<Company>().eq(Company::getCustomerId, customer.getCustomerId()));
            log.info("用户企业：{}", company);
            if (company== null){
                return ResultData.failure("请先设置企业");
            }
            companyId = company.getCompanyId();
        } else {
            companyId = model.getCompanyId();
        }
        if (companyId== null){
            return ResultData.failure("请先设置企业");
        }
        Linkman linkman1 = getOne(new LambdaQueryWrapper<Linkman>()
                .eq(Linkman::getCustomerId, customerId)
                .eq(Linkman::getValidFlag, VALID_TRUE)
                .eq(Linkman::getLinkmanType, model.getLinkmanType())
                .eq(Linkman::getCompanyId, companyId)
                .eq(Linkman::getLinkmanPhone, model.getLinkmanPhone())
                .last("limit 1")
        );
        if (linkman1 != null) {
            return ResultData.failure("当前用户已存在该联系人");
        }
        Linkman linkman = new Linkman();
        BeanUtils.copyProperties(model, linkman);
        Name(model.getLinkmanName(), linkman);
        linkman.setCompanyId(companyId);
        linkman.setCustomerId(customerId);
        linkman.setCreatorId(customerId);
        linkman.setUpdaterId(customerId);
        linkman.setUpdateTime(LocalDateTime.now());
        linkman.setCreateTime(LocalDateTime.now());
        linkman.setValidFlag(VALID_TRUE);
        boolean flag = save(linkman);
        if (flag) {
            return ResultData.success();
        } else {
            return ResultData.failure("内部服务器错误");
        }
    }

    @Override
    public ResultData edit(EditLinkmanModel model) {
        log.info("修改联系人：{}", model);
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        if (!model.getLinkmanPhone().matches(PHONE_NUMBER_VALID_REGEX)) {
            return ResultData.failure("手机号码格式错误");
        }
        //根据用户id查询用户企业
        Long companyId = null;
        if (model.getCompanyId() == null) {
            Company company = companyService.getOne(new LambdaQueryWrapper<Company>().eq(Company::getCustomerId, customer.getCustomerId()));
            if (company== null){
                return ResultData.failure("请先设置企业");
            }
            companyId = company.getCompanyId();
        } else {
            companyId = model.getCompanyId();
        }
        //判断当前用户是否存在重复的标签
        Linkman linkman1 = getOne(new LambdaQueryWrapper<Linkman>()
                .eq(Linkman::getCustomerId, customerId)
                .eq(Linkman::getValidFlag, VALID_TRUE)
                .eq(Linkman::getLinkmanType, model.getLinkmanType())
                .eq(Linkman::getCompanyId, companyId)
                .eq(Linkman::getLinkmanPhone, model.getLinkmanPhone())
                .ne(Linkman::getLinkmanId, model.getLinkmanId())
                .last("limit 1")
        );
        if (linkman1 != null) {
            return ResultData.failure("当前用户已存在该联系人！");
        }
        Linkman linkman = getById(model.getLinkmanId());
        BeanUtils.copyProperties(model, linkman);
        linkman.setUpdateTime(LocalDateTime.now());
        linkman.setUpdaterId(customerId);
        Boolean flag = saveOrUpdate(linkman);
        if (flag) {
            return ResultData.successMsg("更新成功");
        } else {
            return ResultData.failure("更新失败");
        }
    }

    /**
     * 导入联系人数组
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultData importArray(List<AddLinkmanModel> models) {
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        //根据用户id查询用户企业
        // 获取默认企业ID（final修饰）
        Company company = companyService.getOne(new LambdaQueryWrapper<Company>().eq(Company::getCustomerId, customer.getCustomerId()));
        if (company== null){
            return ResultData.failure("请先设置企业");
        }
        Long companyId = company.getCompanyId();
        AtomicReference<Integer> count = new AtomicReference<>(0);
        models.forEach(model -> {
            //对手机号进行校验
            if (!model.getLinkmanPhone().matches(PHONE_NUMBER_VALID_REGEX)) {
                return;
            }
            Long currentCompanyId = Optional.ofNullable(model.getCompanyId())
                    .orElse(companyId);
            Linkman linkman1 = getOne(new LambdaQueryWrapper<Linkman>()
                    .eq(Linkman::getCustomerId, customerId)
                    .eq(Linkman::getValidFlag, VALID_TRUE)
                    .eq(Linkman::getLinkmanType, model.getLinkmanType())
                    .eq(Linkman::getCompanyId, currentCompanyId)
                    .eq(Linkman::getLinkmanPhone, model.getLinkmanPhone()));
            if (linkman1 != null) {
                return;
            }
            Linkman linkman = new Linkman();
            BeanUtils.copyProperties(model, linkman);
            Name(model.getLinkmanName(), linkman);
            linkman.setCompanyId(currentCompanyId);
            linkman.setCustomerId(customerId);
            linkman.setCreatorId(customerId);
            linkman.setUpdaterId(customerId);
            linkman.setUpdateTime(LocalDateTime.now());
            linkman.setCreateTime(LocalDateTime.now());
            linkman.setValidFlag(VALID_TRUE);
            save(linkman);
            count.getAndSet(count.get() + 1);
        });
        log.info("导入联系人数量：{}", count);
        return ResultData.successData(count);
    }

    /**
     * 设置联系人全拼和简拼
     */
    private void Name(String name, Linkman linkman) {
        if (StringUtils.isNotEmpty(name)) {
            // 获取联系人名字的全拼和简拼
            StringBuilder fullSpell = new StringBuilder();
            StringBuilder shortSpell = new StringBuilder();

            for (char c : name.toCharArray()) {
                String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);
                if (pinyinArray != null && pinyinArray.length > 0) {
                    // 取第一个发音（多音字场景）
                    String pinyin = pinyinArray[0].replaceAll("\\d", "");
                    fullSpell.append(pinyin);
                    shortSpell.append(pinyin.charAt(0));
                } else {
                    // 非汉字字符直接保留
                    fullSpell.append(c);
                    shortSpell.append(c);
                }
            }
            // 直接设置到linkman对象
            linkman.setFullSpellName(fullSpell.toString().toLowerCase());
            linkman.setShortSpellName(shortSpell.toString().toLowerCase());
        }
    }

    @Override
    public ResultData del(Long linkmanId) {
        Linkman linkman = getById(linkmanId);
        if (linkman == null) {
            return ResultData.failure("联系人不存在，无需删除");
        }
        linkman.setValidFlag(VALID_FALSE);
        RuleLinkman ruleLinkman = ruleLinkmanService.getOne(
                new LambdaQueryWrapper<RuleLinkman>()
                        .eq(RuleLinkman::getLinkmanId, linkmanId)
                        .last("LIMIT 1")
        );
        Long ruleId = ruleLinkman != null ? ruleLinkman.getRuleId() : null;
        ruleLinkmanService.remove(new LambdaQueryWrapper<RuleLinkman>().eq(RuleLinkman::getLinkmanId, linkmanId));
        List<RuleLinkman> ruleLinkmans = ruleLinkmanService.list(new LambdaQueryWrapper<RuleLinkman>().eq(RuleLinkman::getRuleId, ruleId));
        if (ruleLinkmans.size() == 0) {
            smsRuleService.removeById(ruleId);
        }
        boolean flag = saveOrUpdate(linkman);
        if (flag) {
            return ResultData.success();
        } else {
            return ResultData.failure("内部服务器错误");
        }
    }

    @Override
    public ResultData batchSetLabelOrTeam(BatchSetLabelOrTeamModel model) {
        if (model.getLabelId() == null && model.getTeamId() == null) {
            return ResultData.failure("请选择标签或分组");
        }
        model.getLinkmanIds().forEach(linkmanId -> {
            Linkman linkman = getById(linkmanId);
            if (linkman != null) {
                linkman.setLabelId(model.getLabelId());
                linkman.setTeamId(model.getTeamId());
                saveOrUpdate(linkman);
            }
        });
        return ResultData.success();
    }

    @Override
    public ResultData batchDel(List<Long> linkmanIds) {
        linkmanIds.forEach(linkmanId -> {
            Linkman linkman = getById(linkmanId);
            if (linkman != null) {
                linkman.setValidFlag(VALID_FALSE);
                saveOrUpdate(linkman);
            }
        });
        return ResultData.success();
    }

    /**
     * 判断联系人是否保存
     */
    @Override
    public ResultData isSaved(List<String> phoneLists) {
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        List<String> phoneLists1 = new ArrayList<>();
        phoneLists.forEach(phone -> {
            Linkman linkman = getOne(new LambdaQueryWrapper<Linkman>()
                    .eq(Linkman::getLinkmanPhone, phone)
                    .eq(Linkman::getCustomerId, customerId)
                    .eq(Linkman::getValidFlag, VALID_TRUE)
                    .last("LIMIT 1")
            );
            if (linkman != null) {
                phoneLists1.add(phone);
            }
        });
        return ResultData.successData(phoneLists1);
    }
    
    @Override
    public ResultData getOrganizationStructure(QueryLinkmanModel model) {
        log.info("组织架构model:{}" , model);
        AtomicInteger respect = new AtomicInteger(0);
        AtomicInteger self = new AtomicInteger(0);
        if (model.getTemplateIds().size()>0){
            model.getTemplateIds().forEach(templateId -> {
                SmsTemplate template = smsTemplateService.getById(templateId);
                if (template!=null){
                    //选则的模板中，是否存在模板需要设置尊称；是否设置尊称判断
                    if (template.getContent().contains("$客户尊称$")) {
                        respect.set(NUMBER_1);
                    }
                    //选则的模板中，是否存在模板需要设置自称；模板是否设置自称判断
                    if (template.getContent().contains("$自称$")) {
                        self.set(NUMBER_1);
                    }
                }
            });
        }


        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        
        // 构建查询条件
        LambdaQueryWrapper<Linkman> queryWrapper = new LambdaQueryWrapper<Linkman>()
                .eq(Linkman::getCustomerId, customerId)
                .eq(Linkman::getValidFlag, VALID_TRUE);
        
        // 如果传入了联系人类型进行过滤
        if (model != null && model.getLinkmanType() != null) {
            queryWrapper.eq(Linkman::getLinkmanType, model.getLinkmanType());
        }
        
        // 查询所有联系人
        List<Linkman> allLinkmans = list(queryWrapper);
        log.info("查询结果：{}", allLinkmans);
        if (allLinkmans.size()>0){
            allLinkmans.forEach(linkman -> {
                List<String> reasonList = new ArrayList<>();
                //尊称自称是否设置 0没有，1有
                Integer isName=NUMBER_1;
                if (respect.get() == NUMBER_1 && self.get() == NUMBER_1) {
                    // 添加实际业务逻辑
                    if (StringUtils.isNotEmpty(linkman.getRespectName())&&StringUtils.isNotEmpty(linkman.getSelfName())){
                        isName=NUMBER_1;
                    }else if (StringUtils.isNotEmpty(linkman.getRespectName())||StringUtils.isEmpty(linkman.getSelfName())){
                        isName=NUMBER_0;
                        reasonList.add("当前客户没有设置自称");
                    }else if (StringUtils.isEmpty(linkman.getRespectName())||StringUtils.isNotEmpty(linkman.getSelfName())){
                        isName=NUMBER_0;
                        reasonList.add("当前客户没有设置尊称");
                    }else {
                        isName=NUMBER_0;
                        reasonList.add("当前客户没有设置尊称和自称");
                    }
                }else if (respect.get()==NUMBER_1){
                    if (StringUtils.isNotEmpty(linkman.getRespectName())){
                        isName=NUMBER_1;
                    }else {
                        isName=NUMBER_0;
                        reasonList.add("当前客户没有设置尊称");
                    }
                }else if (self.get()==NUMBER_1){
                    if (StringUtils.isNotEmpty(linkman.getSelfName())){
                        isName=NUMBER_1;
                    }else {
                        isName=NUMBER_0;
                        reasonList.add("当前客户没有设置自称");
                    }
                }else {
                    isName=NUMBER_1;
                }
                // 判断是否在黑名单中
                Integer isInBlack = isInBlackList(linkman.getLinkmanPhone());
                if (isInBlack==NUMBER_0){
                    reasonList.add("当前客户在黑名单中");
                }
                Integer isBirthday=NUMBER_1;
                if (model.getHolidayId()!=null&&model.getHolidayId()==6){
                    // 判断联系人是否设置生日
                    if (linkman.getLinkmanBirthday()!=null){
                        isBirthday=NUMBER_1;
                    }else {
                        isBirthday=NUMBER_0;
                        reasonList.add("当前客户没有设置生日");
                    }
                }
                // 当前联系人是否设置了该节日规则
                Integer isInHoliday = this.isInHolidayRule(linkman.getLinkmanId(),model.getHolidayId(),model.getOperateType(),model.getRuleId());
                if (isInHoliday==NUMBER_0){
                    reasonList.add("当前客户在该节日已设置规则");
                }
                // 判断联系人是否可以选中 包含尊称自称是否设置，生日是否设置，是否在黑名单中
                linkman.setCanSelect(isName==NUMBER_1&&isInHoliday==NUMBER_1&&isBirthday==NUMBER_1&&isInBlack==NUMBER_1?NUMBER_1:NUMBER_0);
                linkman.setReasonList(reasonList);
            });
        }

        // 查询所有相关的部门和标签
        List<Team> allTeams = teamService.list(new LambdaQueryWrapper<Team>()
                .eq(Team::getCustomerId, customerId)
                .eq(Team::getValidFlag, VALID_TRUE));
        
        List<Label> allLabels = labelService.list(new LambdaQueryWrapper<Label>()
                .eq(Label::getCustomerId, customerId)
                .eq(Label::getValidFlag, VALID_TRUE));
        
        // 构建组织架构数据
        Map<String, Object> result = buildOrganizationStructure(allLinkmans, allTeams, allLabels, model);
        
        return ResultData.successData(result);
    }
    /**
     * 判断联系人是否设置了该节日规则
     */
    private Integer isInHolidayRule(Long linkmanId, Long holidayId,Integer operateType,Long ruleId) {
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        Integer count=1;
        if (holidayId!=null){
            List<SmsRule> smsRuleList = smsRuleService.list(new LambdaQueryWrapper<SmsRule>()
                    .eq(SmsRule::getCustomerId, customerId)
                    .eq(SmsRule::getHolidayId, holidayId)
            );
            if (smsRuleList.size()>0){
                for (SmsRule smsRule : smsRuleList){
                    RuleLinkman ruleLinkman = ruleLinkmanService.getOne(new LambdaQueryWrapper<RuleLinkman>()
                            .eq(RuleLinkman::getRuleId, smsRule.getRuleId())
                            .eq(RuleLinkman::getLinkmanId, linkmanId)
                            .ne(operateType==2, RuleLinkman::getRuleId, ruleId)
                    );
                    if (ruleLinkman!=null){
                        count=NUMBER_0;
                    }
                }
            }else {
                count=NUMBER_1;
            }
        }
        return count;
    }
    /**
     * 判断是否在黑名单中
     */
    private Integer isInBlackList(String phone) {
        Customer customer = SaTokenUtilPy.getCustomer();
        Long customerId = customer.getCustomerId();
        int count = blackListService.count(
                new LambdaQueryWrapper<BlackList>()
                        .eq(BlackList::getCustomerId, customerId)
                        .eq(BlackList::getBlackPhone, phone)
        );
        return count==0?1:0;
    }
    
    /**
     * 构建组织架构数据结构
     */
    private Map<String, Object> buildOrganizationStructure(List<Linkman> linkmans, List<Team> teams, List<Label> labels, QueryLinkmanModel model) {
        Map<String, Object> result = new LinkedHashMap<>();
        
        // 确定联系人类型，如果没有传入则默认为客户类型
        Integer linkmanType = (model != null && model.getLinkmanType() != null) ? model.getLinkmanType() : 1;
        
        // 直接构建指定类型的组织结构，不再按类型分组
        buildTypeStructure(result, linkmans, teams, labels, linkmanType);
        
        return result;
    }
    
    /**
     * 构建特定类型的组织结构
     */
    private void buildTypeStructure(Map<String, Object> result, List<Linkman> linkmans, List<Team> teams, List<Label> labels, Integer linkmanType) {
        // 过滤当前类型的联系人
        List<Linkman> typeLinkmans = linkmans.stream()
                .filter(l -> Objects.equals(l.getLinkmanType(), linkmanType))
                .collect(Collectors.toList());
        
        // 根据联系人类型确定分类名称
        String teamCategory = (linkmanType == 0) ? "部门" : "分组";
        String labelCategory = (linkmanType == 0) ? "职位标签" : "标签";
        
        // 构建部门/分组结构
        Map<String, List<Linkman>> teamStructure = new LinkedHashMap<>();
        List<Team> typeTeams = teams.stream()
                .filter(t -> Objects.equals(t.getTeamType(), linkmanType))
                .collect(Collectors.toList());
        
        // 计算每个部门/分组的联系人数量并排序
        List<Team> sortedTeams = typeTeams.stream()
                .sorted((t1, t2) -> {
                    int count1 = (int) typeLinkmans.stream().filter(l -> Objects.equals(l.getTeamId(), t1.getTeamId())).count();
                    int count2 = (int) typeLinkmans.stream().filter(l -> Objects.equals(l.getTeamId(), t2.getTeamId())).count();
                    return Integer.compare(count2, count1); // 从高到低排序
                })
                .collect(Collectors.toList());
        
        // 为所有部门/分组创建条目，按排序后的顺序
        for (Team team : sortedTeams) {
            List<Linkman> teamMembers = typeLinkmans.stream()
                    .filter(l -> Objects.equals(l.getTeamId(), team.getTeamId()))
                    .collect(Collectors.toList());
            teamStructure.put(team.getTeamName(), teamMembers);
        }
        result.put(teamCategory, teamStructure);
        
        // 构建标签结构
        Map<String, List<Linkman>> labelStructure = new LinkedHashMap<>();
        List<Label> typeLabels = labels.stream()
                .filter(l -> Objects.equals(l.getLabelType(), linkmanType))
                .collect(Collectors.toList());
        
        // 计算每个标签的联系人数量并排序
        List<Label> sortedLabels = typeLabels.stream()
                .sorted((l1, l2) -> {
                    int count1 = (int) typeLinkmans.stream().filter(l -> Objects.equals(l.getLabelId(), l1.getLabelId())).count();
                    int count2 = (int) typeLinkmans.stream().filter(l -> Objects.equals(l.getLabelId(), l2.getLabelId())).count();
                    return Integer.compare(count2, count1); // 从高到低排序
                })
                .collect(Collectors.toList());
        
        // 为所有标签创建条目，按排序后的顺序
        for (Label label : sortedLabels) {
            List<Linkman> labelMembers = typeLinkmans.stream()
                    .filter(l -> Objects.equals(l.getLabelId(), label.getLabelId()))
                    .collect(Collectors.toList());
            labelStructure.put(label.getLabelName(), labelMembers);
        }
        result.put(labelCategory, labelStructure);
        
        // 构建"其他"分类（无部门无标签的联系人）
        List<Linkman> othersLinkmans = typeLinkmans.stream()
                .filter(l -> (l.getTeamId() == null || l.getTeamId() == 0) && (l.getLabelId() == null || l.getLabelId() == 0))
                .collect(Collectors.toList());
        result.put("其他", othersLinkmans);
    }
    
    /**
     * 获取联系人类型名称
     */
    private String getLinkmanTypeName(Integer linkmanType) {
        switch (linkmanType) {
            case 0: return "员工";
            case 1: return "客户";
            case 2: return "亲朋好友";
            default: return "未知类型";
        }
    }

    /**
     * excel导入联系人（支持不定列名）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultData importExcel(File file) {
        try (ExcelReader reader = ExcelUtil.getReader(file)) {
            List<Linkman> records = new ArrayList<>();
            StringBuilder error = new StringBuilder();
            Customer customer = SaTokenUtilPy.getCustomer();
            Long customerId = customer.getCustomerId();
            log.info("开始导入联系人:{}", reader.toString());
            // 1. 获取Excel的所有列名
            List<String> columnNames = new ArrayList<>(reader.getHeaderAlias().keySet());
            log.info("Excel列名：{}", columnNames);
            if (columnNames.isEmpty()) {
                //读取第一行
                List<Object> firstRow = reader.readRow(0);
                if (firstRow != null && !firstRow.isEmpty()) {
                    columnNames = firstRow.stream()
                            .map(Object::toString)
                            .collect(Collectors.toList());
                    log.info("强制使用第一行作为列名：{}", columnNames);

                    // 设置新的起始行（跳过标题行）
                    reader.setSheet(0);
                    reader.read(1, Integer.MAX_VALUE);
                } else {
                    String msg = "Excel文件没有列名且第一行为空";
                    log.error(msg);
                    throw new RuntimeException(msg);
                }
            }

            // 2. 建立列名与Linkman属性的映射关系
            Map<String, String> columnMapping = buildColumnMapping(columnNames);
            log.info("列名与属性的映射关系：{}", columnMapping);

            // 3. 读取所有行数据
            List<Map<String, Object>> readAll = reader.readAll();
            // 新增：查询当前客户已存在的手机号
            Set<String> existPhones = this.list(new LambdaQueryWrapper<Linkman>()
                            .select(Linkman::getLinkmanPhone)
                            .eq(Linkman::getCustomerId, customerId)
                            .eq(Linkman::getValidFlag, VALID_TRUE))
                    .stream()
                    .map(Linkman::getLinkmanPhone)
                    .collect(Collectors.toSet());
            log.info("已存在的手机号：{}", existPhones);
            // 新增：用于跟踪当前批次的手机号
            Set<String> batchPhones = new HashSet<>();

            for (Map<String, Object> row : readAll) {
                try {
                    Linkman linkman = new Linkman();
                    // 4. 动态设置属性
                    for (Map.Entry<String, String> entry : columnMapping.entrySet()) {
                        String excelColumn = entry.getKey();
                        String propertyName = entry.getValue();
                        Field field = Linkman.class.getDeclaredField(propertyName);
                        field.setAccessible(true);
                        Integer changValue = null;
                        LocalDate localDate = null;
                        if (row.containsKey(excelColumn) && row.get(excelColumn) != null) {
                            Object value = row.get(excelColumn);
                            log.info("列名：{}，属性名：{}，属性值：{}", excelColumn, propertyName, value);

                            if ("birthdayType".equals(propertyName)) {
                                log.info("生日类型：{}", excelColumn);
                                if ("农历".equals(value) || "0".equals(value)) {
                                    changValue = NUMBER_0;
                                } else if ("公历".equals(value) || "1".equals(value) || "阳历".equals(value)) {
                                    changValue = NUMBER_1;
                                }
                            }
                            if ("linkmanSex".equals(propertyName)) {
                                if ("男".equals(value) || "1".equals(value)) {
                                    changValue = NUMBER_1;
                                } else if ("女".equals(value) || "0".equals(value)) {
                                    changValue = NUMBER_0;
                                }
                            }
                            if ("linkmanType".equals(propertyName)) {
                                if ("员工".equals(value)) {
                                    changValue = NUMBER_0;
                                } else if ("客户".equals(value)) {
                                    changValue = NUMBER_1;
                                } else if ("亲友".equals(value)) {
                                    changValue = NUMBER_2;
                                }
                            }
                            if ("linkmanBirthday".equals(propertyName)) {
                                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                                localDate = LocalDate.parse(value.toString(), formatter);
                            }
                            if ("teamId".equals(propertyName) && linkman.getLinkmanType() != null) {
                                Team team = teamService.getOne(new LambdaQueryWrapper<Team>()
                                        .like(Team::getTeamName, value)
                                        .eq(Team::getCustomerId, customerId)
                                        .eq(Team::getValidFlag, VALID_TRUE)
                                );
                                if (team == null) {
                                    team.setTeamName((String) value);
                                    team.setTeamType(linkman.getLinkmanType());
                                    team.setCustomerId(customerId);
                                    team.setCreateTime(LocalDateTime.now());
                                    team.setUpdateTime(LocalDateTime.now());
                                    team.setCreatorId(customerId);
                                    team.setUpdaterId(customerId);
                                    team.setValidFlag(VALID_TRUE);
                                    team.insert();
                                }
                                changValue = Math.toIntExact(team.getTeamId());
                            }
                            if ("labelId".equals(propertyName) && linkman.getLinkmanType() != null) {
                                Label label = labelService.getOne(new LambdaQueryWrapper<Label>()
                                        .like(Label::getLabelName, value)
                                        .eq(Label::getCustomerId, customerId)
                                        .eq(Label::getValidFlag, VALID_TRUE)
                                );
                                if (label == null) {
                                    label.setLabelName((String) value);
                                    label.setLabelType(linkman.getLinkmanType());
                                    label.setCustomerId(customerId);
                                    label.setCreateTime(LocalDateTime.now());
                                    label.setUpdateTime(LocalDateTime.now());
                                    label.setCreatorId(customerId);
                                    label.setUpdaterId(customerId);
                                    label.setValidFlag(VALID_TRUE);
                                    label.insert();
                                }
                                changValue = Math.toIntExact(label.getLabelId());
                            }
                            if (changValue != null && localDate == null) {
                                field.set(linkman, changValue);
                            } else if (changValue == null && localDate == null) {
                                log.info("当前联系人：{}", value);
                                value = value.toString();

                                field.set(linkman, value);
                                log.info("当前联系人：{}", linkman);
                            } else {
                                field.set(linkman, localDate);
                            }
                            log.info("当前联系人：{}", linkman);
                        }
                    }
                    log.info("当前联系人：{}", linkman);
                    // 验证必要字段
                    if (StringUtils.isBlank(linkman.getLinkmanPhone())) {
                        continue;
                    }
                    log.info("当前联系人：{}", existPhones);
                    log.info("当前联系人：{}", batchPhones);

                    String currentPhone = linkman.getLinkmanPhone();
                    // 静默过滤重复号码
                    if (existPhones.contains(currentPhone) || batchPhones.contains(currentPhone)) {
                        continue;
                    }
                    //过滤手机号格式错误
                    if (!linkman.getLinkmanPhone().matches(PHONE_NUMBER_VALID_REGEX)) {
                        continue;
                    }
                    batchPhones.add(currentPhone);
                    records.add(linkman);
                } catch (Exception e) {
                    log.error("联系人导入异常", e);
                    error.append("第").append(readAll.indexOf(row) + 1)
                            .append("行数据错误: ").append(e.getMessage()).append("; ");
                }
            }

            if (records.isEmpty()) {
                return ResultData.failure("没有有效数据可导入");
            }
            return ResultData.successData(records);
        } catch (Exception e) {
            log.error("联系人导入异常", e);
            return ResultData.failure("文件解析失败：" + e.getMessage());
        }
    }

    /**
     * 建立列名与Linkman属性的映射关系
     */
    private Map<String, String> buildColumnMapping(List<String> columnNames) {
        // 预定义的列名映射（支持多种可能的列名）
        Map<String, String> predefinedMappings = new HashMap<>();

        // 联系人姓名可能的列名
        predefinedMappings.put("联系人姓名", "linkmanName");
        predefinedMappings.put("姓名", "linkmanName");
        predefinedMappings.put("用户名", "linkmanName");
        predefinedMappings.put("名字", "linkmanName");
        predefinedMappings.put("联系人", "linkmanName");
        predefinedMappings.put("联系人名字", "linkmanName");
        predefinedMappings.put("名称", "linkmanName");
        predefinedMappings.put("联系人名称", "linkmanName");
        predefinedMappings.put("全名", "linkmanName");
        predefinedMappings.put("真实姓名", "linkmanName");
        predefinedMappings.put("会员姓名", "linkmanName");
        predefinedMappings.put("用户姓名", "linkmanName");
        predefinedMappings.put("称呼", "linkmanName");
        predefinedMappings.put("客户姓名", "linkmanName");
        predefinedMappings.put("name", "linkmanName");
        predefinedMappings.put("nickname", "linkmanName");
        // 性别可能的列名
        predefinedMappings.put("性别", "linkmanSex");
        predefinedMappings.put("男/女", "linkmanSex");
        predefinedMappings.put("性别标识", "linkmanSex");
        predefinedMappings.put("sex", "linkmanSex");
        //生日可能的列名
        predefinedMappings.put("生日", "linkmanBirthday");
        predefinedMappings.put("出生日期", "linkmanBirthday");
        predefinedMappings.put("birthday", "linkmanBirthday");
        //生日类型可能的列名
        predefinedMappings.put("生日类型", "birthdayType");
        predefinedMappings.put("农历标识", "birthdayType");
        predefinedMappings.put("公历标识", "birthdayType");
        predefinedMappings.put("历法类型", "birthdayType");

        // 电话可能的列名
        predefinedMappings.put("电话", "linkmanPhone");
        predefinedMappings.put("手机号码", "linkmanPhone");
        predefinedMappings.put("联系电话", "linkmanPhone");
        predefinedMappings.put("手机号", "linkmanPhone");
        predefinedMappings.put("手机", "linkmanPhone");
        predefinedMappings.put("号码", "linkmanPhone");
        predefinedMappings.put("固定电话", "linkmanPhone");
        predefinedMappings.put("电话号码", "linkmanPhone");
        predefinedMappings.put("phone", "linkmanPhone");
        //微信可能的列名
        predefinedMappings.put("微信", "linkmanWechat");
        predefinedMappings.put("微信号", "linkmanWechat");
        predefinedMappings.put("微信账号", "linkmanWechat");
        predefinedMappings.put("微信帐户", "linkmanWechat");
        predefinedMappings.put("微信联系方式", "linkmanWechat");
        predefinedMappings.put("联系人微信", "linkmanWechat");
        predefinedMappings.put("wechat", "linkmanWechat");
        predefinedMappings.put("weixin", "linkmanWechat");
        //尊称可能的列名
        predefinedMappings.put("尊称", "respectName");
        predefinedMappings.put("称呼", "respectName");
        predefinedMappings.put("称谓", "respectName");
        predefinedMappings.put("姓名前的称呼", "respectName");
        //自称可能的列名
        predefinedMappings.put("自称", "selfName");
        predefinedMappings.put("自我称呼", "selfName");
        predefinedMappings.put("个人称谓", "selfName");
        predefinedMappings.put("自称名称", "selfName");
        // 邮箱可能的列名
        predefinedMappings.put("邮箱", "linkmanEmail");
        predefinedMappings.put("电子邮件", "linkmanEmail");
        predefinedMappings.put("邮件", "linkmanEmail");
        predefinedMappings.put("email", "linkmanEmail");
        predefinedMappings.put("e-mail", "linkmanEmail");
        predefinedMappings.put("联系邮箱", "linkmanEmail");
        predefinedMappings.put("联系人邮箱", "linkmanEmail");
        predefinedMappings.put("客服邮箱", "linkmanEmail");
        predefinedMappings.put("邮箱地址", "linkmanEmail");
        predefinedMappings.put("邮箱账号", "linkmanEmail");
        //分组可能的列名
        predefinedMappings.put("分组", "teamId");
        predefinedMappings.put("分组名称", "teamId");
        predefinedMappings.put("部门名称", "teamId");
        predefinedMappings.put("部门", "teamId");
        //标签可能的列名
        predefinedMappings.put("标签", "labelId");
        predefinedMappings.put("标签名称", "labelId");
        // 创建最终映射关系
        Map<String, String> columnMapping = new HashMap<>();

        for (String column : columnNames) {
            // 去除可能的空格
            String cleanColumn = column.trim();

            // 查找匹配的预定义映射
            for (Map.Entry<String, String> entry : predefinedMappings.entrySet()) {
                if (entry.getKey().equalsIgnoreCase(cleanColumn)) {
                    columnMapping.put(column, entry.getValue());
                    break;
                }
            }

            // 如果没有匹配到预定义的，尝试智能匹配（简单实现）
            if (!columnMapping.containsKey(column)) {
                String probableProperty = guessPropertyName(cleanColumn);
                if (probableProperty != null) {
                    columnMapping.put(column, probableProperty);
                }
            }
        }

        return columnMapping;
    }

    /**
     * 简单的智能猜测属性名（当预定义映射不匹配时使用）
     */
    private String guessPropertyName(String columnName) {
        // 清洗列名：去除空格/下划线/中文括号，统一小写
        String cleanName = columnName
                .replaceAll("[\\s_()（）]", "")
                .toLowerCase();

        // 处理带说明的列名（如"电话(必填)" -> "电话"）
        if (cleanName.contains("（") || cleanName.contains("(")) {
            cleanName = cleanName.split("[（(]")[0];
        }

        // 增强字段映射（根据Linkman实体实际字段）
        if (cleanName.matches("(电话|手机|联系方式|mobile|phone|tel|dh|sjhm)")) {
            return "linkmanPhone";
        } else if (cleanName.matches("(邮箱|邮件|email|e-mail|yx|yxdz)")) {
            return "linkmanEmail";
        }

        // 保留原有基础匹配
        if (cleanName.contains("姓名") || cleanName.contains("名字") || cleanName.contains("联系人")) {
            return "linkmanName";
        }

        return null;
    }
    /**获取所有结构联系人*/
    @Override
    public ResultData getAllLinkman() {
        List<TreeNodeVo> tree = new ArrayList<>();

        // 创建客户节点及其子节点
        TreeNodeVo customerNode = new TreeNodeVo("1", "客户");
        List<TreeNodeVo> customerChildren = new ArrayList<>();
        customerChildren.add(new TreeNodeVo("0", "客户分组"));
        customerChildren.add(new TreeNodeVo("1", "客户标签"));
        customerChildren.add(new TreeNodeVo("2", "其他（未分组未打标签）"));
        customerNode.setChildren(customerChildren);

        // 创建员工节点及其子节点
        TreeNodeVo employeeNode = new TreeNodeVo("2", "员工");
        List<TreeNodeVo> employeeChildren = new ArrayList<>();
        employeeChildren.add(new TreeNodeVo("0", "部门"));
        employeeChildren.add(new TreeNodeVo("1", "标签/职位"));
        employeeChildren.add(new TreeNodeVo("2", "其他（未分组未打标签）"));
        employeeNode.setChildren(employeeChildren);

        // 创建亲友节点及其子节点
        TreeNodeVo friendNode = new TreeNodeVo("3", "亲友");
        List<TreeNodeVo> friendChildren = new ArrayList<>();
        friendChildren.add(new TreeNodeVo("0", "亲友分组"));
        friendChildren.add(new TreeNodeVo("1", "亲友标签"));
        friendChildren.add(new TreeNodeVo("2", "其他（未分组未打标签）"));
        friendNode.setChildren(friendChildren);

        // 创建其他节点
        TreeNodeVo otherNode = new TreeNodeVo("4", "其它");
        List<Linkman> linkmanList = list(new LambdaQueryWrapper<Linkman>()
                .eq(Linkman::getLinkmanType, null)
                .eq(Linkman::getLabelId, null)
                .eq(Linkman::getTeamId, null)
                .eq(Linkman::getValidFlag, 1)
        );
        // 转换Linkman为TreeNodeVo
        List<TreeNodeVo> otherChildren = linkmanList.stream()
                .map(l -> new TreeNodeVo(
                        l.getLinkmanId().toString(),
                        l.getLinkmanName() + " (" + l.getLinkmanPhone() + ")"
                ))
                .collect(Collectors.toList());

        otherNode.setChildren(otherChildren);


        // 将所有根节点添加到树中
        tree.add(customerNode);
        tree.add(employeeNode);
        tree.add(friendNode);
        tree.add(otherNode);

        return ResultData.successData(tree);
    }
}
